package cn.ultrarisk.scadmin.manager.biz.solr.service;

import cn.ultrarisk.mybatis.extension.query.Query;
import cn.ultrarisk.mybatis.extension.query.Updater;
import cn.ultrarisk.scadmin.manager.biz.common.context.OperationType;
import cn.ultrarisk.scadmin.manager.biz.common.service.OperationLogService;
import cn.ultrarisk.scadmin.manager.biz.solr.context.SolrState;
import cn.ultrarisk.scadmin.manager.biz.solr.dao.SolrCollectionDAO;
import cn.ultrarisk.scadmin.manager.biz.solr.dao.SolrReplicaDAO;
import cn.ultrarisk.scadmin.manager.biz.solr.dao.SolrShardDAO;
import cn.ultrarisk.scadmin.manager.biz.solr.entity.SolrCollection;
import cn.ultrarisk.scadmin.manager.biz.solr.entity.SolrReplica;
import cn.ultrarisk.scadmin.manager.biz.solr.entity.SolrShard;
import cn.ultrarisk.scadmin.manager.biz.solr.factory.HttpSolrServerFactory;
import cn.ultrarisk.scadmin.manager.util.JsonUtil;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.request.CoreAdminRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.List;

/**
 * SolrReplicaService
 *
 * @author sevendlong(lin23871@163.com)
 * @date 2014/5/13
 * @since V1.0
 */
@Service
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class SolrReplicaService {
    @Autowired
    private SolrCollectionDAO solrCollectionDAO;
    @Autowired
    private SolrReplicaDAO solrReplicaDAO;
    @Autowired
    private SolrShardDAO solrShardDAO;
    @Autowired
    private OperationLogService operationLogService;
    @Autowired
    private HttpSolrServerFactory solrServerFactory;

    public SolrReplica create(String coreName, Integer collectionId, String shardName, Integer nodeId, boolean isLog) {
        SolrCollection collection = solrCollectionDAO.get(collectionId, SolrCollection.NAME);
        SolrShard shard = solrShardDAO.getByName(shardName, collectionId);
        if (shard == null) {
            shard = solrShardDAO.create(shardName, collectionId);
        }

        SolrReplica replica = new SolrReplica();
        replica.setCoreName(coreName);
        replica.setReplicaName("");
        replica.setState(SolrState.RECOVERING);
        replica.setCollectionId(collectionId);
        replica.setShardId(shard.getId());
        replica.setNodeId(nodeId);
        replica.setLeader(false);
        replica.setAvailable(true);
        replica.setInstanceDir(replica.getCoreName());
        replica.setDataDir("data");
        replica.setConfigXml("solrconfig.xml");
        replica.setSchemaXml("schema.xml");
        replica.setUpdateTime(System.currentTimeMillis());
        solrReplicaDAO.create(replica);

        try {
            CoreAdminRequest.Create request = new CoreAdminRequest.Create();
            request.setCoreName(coreName);
            request.setInstanceDir(coreName);
            request.setDataDir("data");
            request.setConfigName("solrconfig.xml");
            request.setSchemaName("schema.xml");
            request.setCollection(collection.getName());
            request.setShardId(shardName);
            request.process(solrServerFactory.getNodeServer(replica.getId()));
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (isLog) {
            operationLogService.createSolrReplicaLog(OperationType.SOLR_REPLICA_CREATE, replica.getId());
        }
        return replica;
    }

    /*
    public void optimize(Integer id, Integer maxSegments) throws IOException, SolrServerException {
        HttpSolrServer server = solrServerFactory.getCoreServer(id);
        server.optimize(false, false, maxSegments);
    }

    public void reload(Integer id) throws IOException, SolrServerException {
        SolrReplica replica = solrReplicaDAO.get(id, SolrReplica.CORE_NAME);
        HttpSolrServer server = solrServerFactory.getNodeServer(id);
        CoreAdminRequest.reloadCore(replica.getCoreName(), server);
    }
    */

    public void delete(Integer id, boolean isLog) throws IOException, SolrServerException {
        SolrReplica replica = solrReplicaDAO.get(id, SolrReplica.CORE_NAME, SolrReplica.AVAILABLE);

        if (replica.getAvailable()) {
            CoreAdminRequest.unloadCore(replica.getCoreName(), solrServerFactory.getNodeServer(id));
        }

        if (isLog) {
            operationLogService.createSolrReplicaLog(OperationType.SOLR_REPLICA_DELETE, id);
        }
        solrReplicaDAO.delete(id);
    }

    public SolrReplica saveByZKInfo(String replicaName, JsonUtil.MapWrapper replicaStateMap, Integer shardId, Integer collectionId, Integer nodeId, Long updateTime) {
        SolrState state = SolrState.get(replicaStateMap.getStringByPath("state"));
        String coreName = replicaStateMap.getStringByPath("core");
        Boolean leader = replicaStateMap.getBooleanByPath("leader");
        if (leader != null && leader) {
            state = SolrState.LEADER;
        }

        Query query = Query.query(SolrReplica.SHARD_ID, shardId).eq(SolrReplica.COLLECTION_ID, collectionId)
                .eq(SolrReplica.NODE_ID, nodeId).eq(SolrReplica.CORE_NAME, coreName);
        SolrReplica replica = solrReplicaDAO.get(query);

        if (replica == null) {
            replica = new SolrReplica(coreName, replicaName, state, leader, shardId, collectionId, nodeId);
        }

        replica.setReplicaName(replicaName);
        replica.setLeader(leader);
        replica.setState(state);
        replica.setUpdateTime(updateTime);
        replica.setAvailable(true);

        if (replica.getId() == null) {
            solrReplicaDAO.create(replica);
        } else {
            solrReplicaDAO.update(replica.getId(), Updater.update(SolrReplica.REPLICA_NAME, replicaName).addField(SolrReplica.LEADER, leader)
                    .addField(SolrReplica.STATE, state).addField(SolrReplica.UPDATE_TIME, updateTime).addField(SolrReplica.AVAILABLE, true));
        }
        return replica;
    }

    public void updateBySolrInfo(Integer id, JsonUtil.MapWrapper statusMap) {
        Updater updater = new Updater();
        updater.addField(SolrReplica.SEGMENT_NUM, statusMap.getIntByPath("index.segmentCount"));
        updater.addField(SolrReplica.LAST_MODIFIED, statusMap.getGMTDateByPath("index.lastModified"));
        updater.addField(SolrReplica.VERSION, statusMap.getIntByPath("index.version"));
        updater.addField(SolrReplica.INSTANCE_DIR, statusMap.getStringByPath("instanceDir"));
        updater.addField(SolrReplica.DATA_DIR, statusMap.getStringByPath("dataDir"));
        updater.addField(SolrReplica.CONFIG_XML, statusMap.getStringByPath("config"));
        updater.addField(SolrReplica.SCHEMA_XML, statusMap.getStringByPath("config"));
        updater.addField(SolrReplica.DIRECTORY, statusMap.getStringByPath("index.directory"));
        updater.addField(SolrReplica.START_TIME, statusMap.getGMTDateByPath("startTime"));
        updater.addField(SolrReplica.COMMIT_TIME, statusMap.getLongByPath("index.userData.commitTimeMSec"));
        updater.addField(SolrReplica.UPTIME, statusMap.getLongByPath("uptime"));
        solrReplicaDAO.update(id, updater);
    }

    public void disable(List<Integer> ids) {
        solrReplicaDAO.update(Query.inQuery(SolrReplica.ID, ids), Updater.update(SolrReplica.AVAILABLE, false));
    }

    /**
     * 清除过期的solrReplica
     *
     * @query expiredTime
     */
    public void clearExpiredData(long expiredTime) {
        Query query = Query.ltQuery(SolrReplica.UPDATE_TIME, expiredTime);
        solrReplicaDAO.delete(query);
    }
}
